package tiny.soft.com.common.util;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tiny.soft.com.common.api.IBaseMapper;
import tk.mybatis.mapper.common.BaseMapper;
import tk.mybatis.mapper.entity.Condition;

import java.util.List;

/**
 * 数据库批量操作工具类
 *
 * @ClassName BatchOperationUtil
 * @Author 陈池
 * @Date 2019/8/13 16:33
 * @Version 1.0
 **/
@Component
public class BatchOperationUtils {
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    /**
      * xunj
      * @Author 宋晓虎
      * @Date 2019/8/20 下午 01:57
    **/
    private static final int circleExecNum=1000;
    /**
     * 批量插入
     * @return int
     * @Author 陈池
     * @Date 2019/8/13 16:35
     **/
    public SqlSession getSession() {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory()
                .openSession(ExecutorType.BATCH, false);
        return sqlSession;
    }


    /**
     * 批量插入，每batchSize条数据提交一次
     * @Author 柳时光
     * @Date 2019/10/1 10:26
     * @param list 需要批量插入的数据list
     * @param mapperClass 对应数据的Mapper的Class
     * @param batchSize 批量分页插入，每页数量，-1 不分页， 分页数量大于1，推荐不小于100
     * @return int 插入成功数量
     **/
    public int batchInsert(List list, Class mapperClass, int batchSize){
        batchSize = batchSize>=0 && batchSize<=2 ? 1000 : batchSize;

        int successNum = 0;

        SqlSession sqlSession = null;

        try {
            sqlSession = getSession();
            BaseMapper mapper = (BaseMapper) sqlSession.getMapper(mapperClass);

            for (int i = 0; i < list.size(); i++) {
                mapper.insert(list.get(i));
                successNum++;
                //每1000条提交一次防止内存溢出
                if (batchSize > 0) {
                    if (i % batchSize == (batchSize - 1)) {
                        sqlSession.commit();
                        sqlSession.clearCache();
                    }
                }
            }
            sqlSession.commit();
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
            throw  e;
        }
        return successNum;
    }


    /**
      *
      * @Author 宋晓虎
      * @Date 2019/8/20 上午 11:38
      * @param list
      * @param mapperClazz
      * @return int
    **/
    @Transactional
    public <T> int batchPageInsert(List<T> list, Class mapperClazz,int batchTimes) {
        int insert = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = getSession();
            IBaseMapper mapper = (IBaseMapper) sqlSession.getMapper(mapperClazz);
            if(CollectionUtil.isEmpty(list)){
                return 0;
            }
            int circleTimes=list.size()/batchTimes;
            for(int m=0;m<circleTimes;m++){
                List<T>subList=list.subList(0,batchTimes);
                for (T t : list) {
                    int i = mapper.insert(t);
                    insert++;
                }
                sqlSession.commit();
                subList.clear();
            }

            if(list.size()>0){
                for (T t : list) {
                    int i = mapper.insert(t);
                }
                sqlSession.commit();
                list.clear();
            }
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
            throw  e;
        }
        return insert;
    }
    /**
     *
     * @Author 宋晓虎
     * @Date 2019/8/20 上午 11:38
     * @param list
     * @param mapperClazz
     * @return int
     **/
    @Transactional
    public <T> int batchPageInsert(List<T> list, Class mapperClazz) {
        return this.batchPageInsert(list,mapperClazz,circleExecNum);
    }
    /**
     *
     * @Author 宋晓虎
     * @Date 2019/8/20 上午 11:38
     * @param list
     * @param mapperClazz
     * @return int
     **/
    @Transactional
    public <T> int batchInsert(List<T> list, Class mapperClazz) {
        int insert = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = getSession();
            BaseMapper mapper = (BaseMapper) sqlSession.getMapper(mapperClazz);
            if(CollectionUtil.isEmpty(list)){
                return 0;
            }
            for (T t : list) {
                int i = mapper.insert(t);
                insert = insert + i;
            }
            sqlSession.commit();
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
            throw  e;
        }
        return insert;
    }
    /**
     * 批量更新
     *
     * @param list
     * @param mapperClazz
     * @return int
     * @Author 陈池
     * @Date 2019/8/13 16:37
     **/
    @Transactional
    public <T> int batchUpdate(List<T> list, Class mapperClazz) {
        int update = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = getSession();
            BaseMapper mapper = (BaseMapper) sqlSession.getMapper(mapperClazz);
            for (T t : list) {
                int i = mapper.updateByPrimaryKeySelective(t);
                update = update + i;
            }
            sqlSession.commit();
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
            throw  e;
        }
        return update;
    }

    /**
     * 批量更新
     *
     * @param list
     * @return int
     * @Author 陈池
     * @Date 2019/8/13 16:37
     **/
    @Transactional
    public <T> int batchUpdate(List<T> list, List<Condition>conditions, Class mapperClazz) {
        int update = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = getSession();
            IBaseMapper mapper = (IBaseMapper) sqlSession.getMapper(mapperClazz);
            for(int i=0;i<list.size();i++){
                mapper.updateByConditionSelective(list.get(i),conditions.get(i));
                update = update + i;
            }
            sqlSession.commit();
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
            throw  e;
        }
        return update;
    }
}
